package api

import (
	"gitee.com/go-course/go11/vblog/apps/blog"
	"gitee.com/go-course/go11/vblog/ioc"
	"gitee.com/go-course/go11/vblog/protocol/middlewares"
	"github.com/gin-gonic/gin"
)

// 为啥要用一个函数来构造
// 初始化一些基础数据
// 具体传递实现，在什么时候决定
// 典型的面向接口编程
// 使用ioc 替换掉 直接依赖
func NewHandler() *Handler {
	return &Handler{}
}

// 处理Http报文的处理器
// 又这个handler类来负责实现具体的API 接口
type Handler struct {
	// 需要一个业务的具体实现
	svc blog.Service
}

// 让他从Ioc中获取依赖的对象
func (h *Handler) Init() error {
	// 获取出来的这个对象是个Ioc对象
	// 使用类型断言 来把any --> 正在的业务对象
	// 内置逻辑: blog.AppName 名称 --> blog.Service 类型  object.(type struct<object>|interface)
	//  var a = any   a.(string)
	// svc = ioc.GetController(blog.AppName)
	// svc.(blog.Service)
	h.svc = ioc.GetController(blog.AppName).(blog.Service)
	return nil
}

func (h *Handler) Name() string {
	// 使用不同的存储来保存对象 controller map, api map
	return blog.AppName
}

// 把你的请求和Http 路由对应上
// r 就是一个gin http 的路由器
// URL:  /vblog/api/v1/blogs --->  那个Handler(处理函数)
func (h *Handler) Registry(r gin.IRouter) {
	// 业务模块自己觉得使用哪些中间件, 所有的后面的接口都需要认证

	// 为这个业务单独生成一个子Router,不要和全局的Router混用
	// "/vblog/api/v1/blogs" 就是URL的前缀
	// 子Router的中间件加载时又顺序控制
	// sr := r.Group("/vblog/api/v1/blogs")
	// 子路由, root(中间件是全局) ---> sub router(只属于sub router)
	// root.Group(prefix_path) ---> sub router
	// 为每个模块生成了一个子路由, 每个模块的路由由子路由单独控制
	// 每个模块都需要写 这么一长串合理吗?
	// 最好这里的r 就是一个子路由
	//  考虑把子路由的生成 路由ioc里面去处理
	// 对所有的对象统一执行 初始化

	// 下面是ioc的逻辑
	// 把所有 api handler 注册root 路由
	// func InitHttpApi(r gin.IRouter) error {
	// 	for k, v := range api {
	// 		err := v.Init()
	// 		if err != nil {
	// 			return fmt.Errorf("init %s error, %s", k, err)
	// 		}
	//      为每一模块生成一个子路由  r.Group()
	// 		v.Registry(r)
	// 	}

	// 	return nil
	// }

	// 查询博客列表页, 不需要认证, 这个要放在加载中间件 之前
	// prefgix + 当前定义的url
	// /vblog/api/v1/blogs + ""
	r.GET("", h.QueryBlog)

	// 文章详情的接口
	r.GET("/:id", h.DescribeBlog)

	// 后面的接口都需要认证
	// 因为IRouter是全局
	// 当前的r 是Root Router
	// 和加载顺序有关系是子Router
	r.Use(middlewares.Auth)

	// 这个是创建博客的请求, 用户的请求的放到body, 因此Get是不携带body
	// RESTful风格的API, 以POST表示资源的创建
	r.POST("", h.CreateBlog)
	r.PUT("/:id", h.UpdateBlog)
	r.DELETE("/:id", h.DeleteBlog)
}

// import _ "gitee.com/go-course/go11/vblog/apps/blog/api"
// 怎么控制加载哪些业务单元
func init() {
	ioc.RegistryHttpApi(&Handler{})
}
